package com.xuyuan.concurrent.lock;

import org.junit.jupiter.api.Test;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CountDownLatchExample {

    /**
     * CountDownLatch - 同时开始执行
     *
     * @throws InterruptedException
     */
    @Test
    public void test1() throws InterruptedException {
        int numWorkers = 3; // 定义工人数量
        CountDownLatch startSignal = new CountDownLatch(1); // 创建CountDownLatch对象，初始计数器为1

        ExecutorService executor = Executors.newFixedThreadPool(numWorkers);

        for (int i = 0; i < numWorkers; i++) {
            int workerId = i;
            executor.submit(() -> {
                try {
                    System.out.println("工人" + workerId + "准备中...");
                    startSignal.await(); // 等待主线程发出开始信号

                    // 工人开始执行任务
                    System.out.println("工人" + workerId + "开始执行任务");

                    // 模拟工作过程
                    Thread.sleep((long) (Math.random() * 3000));

                    System.out.println("工人" + workerId + "任务完成");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

        System.out.println("主线程准备中...");
        Thread.sleep(3000); // 模拟主线程准备过程

        startSignal.countDown(); // 发出开始信号，计数器减1
        System.out.println("主线程发出开始信号");

        executor.shutdown();
        while (!executor.isTerminated()) {
            // 等待所有工人线程执行完毕
        }
        System.out.println("所有工人任务完成，主线程继续执行");
    }

    /**
     * CountDownLatch - 都结束继续执行
     */
    @Test
    public void test2() throws InterruptedException {
        int numWorkers = 3; // 定义工人数量
        CountDownLatch startSignal = new CountDownLatch(numWorkers); // 创建CountDownLatch对象，初始计数器为1
        ExecutorService executor = Executors.newFixedThreadPool(numWorkers);

        for (int i = 0; i < numWorkers; i++) {
            int workerId = i;
            executor.submit(() -> {
                try {
                    System.out.println("工人" + workerId + "准备中...");
                    System.out.println("工人" + workerId + "开始执行任务");
                    Thread.sleep((long) (Math.random() * 3000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    System.out.println("工人" + workerId + "任务完成");
                    startSignal.countDown();
                }
            });
        }

        startSignal.await();
        executor.shutdown();
        while (!executor.isTerminated()) {
            // 等待所有工人线程执行完毕
        }
        System.out.println("所有工人任务完成，主线程继续执行");
    }
}
